﻿/// -----------------------------------------------------------------
/// ErrorHandler.cs: Contains static methods to handle Errors and Exceptions
/// License: see http://mve.codeplex.com/license; All Rights follows the MS-PL
/// Current owner: shiniwa
/// The project decription: please refer to http://codeplex.com/mve/
/// -----------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Security;

namespace MVEContentSvc
{
    /// <summary>
    /// Contains static methods to handle Errors and Exceptions 
    /// that might occur in the main program. This Service does
    /// not contain any advanced Error/Exception handling, this
    /// class is mostly used as a logging facility.
    /// </summary>
    internal static class ErrorHandler
    {
        /// <summary>
        /// Set the Target for logging. By default the target is None,
        /// meaning no output is produced from the LogMessage Call.
        /// </summary>
        internal static ErrorLoggingModes LoggingMode =
            ErrorLoggingModes.None;

        /// <summary>
        /// Path to a text file used in combination with the ErrorLoggingMode
        /// of File.
        /// </summary>
        internal static string LogFilePath = string.Empty;

        /// <summary>
        /// Logs a single error message to the current target LoggingMode.
        /// </summary>
        /// <param name="Message">The message to log</param>
        /// <param name="AddLineBreak">Tells whether an extra Line Break 
        /// should be added after the message.</param>
        internal static void LogMessage(string Message, bool AddLineBreak)
        {
            if (string.IsNullOrEmpty(Message))
                throw new ArgumentException(
                    Resources.LogMessageEmptyOrNull);

            string methodName = "";
            string tyepeName = "";

            //Get some additional data on the current stack frame.
            try
            {
                System.Diagnostics.StackFrame frame = new System.Diagnostics.StackFrame(2, true);
                methodName = frame.GetMethod().Name;
                tyepeName = frame.GetMethod().DeclaringType.FullName;
            }
            catch (ArgumentOutOfRangeException)
            {
                methodName = Resources.UnknownMethodName;
                tyepeName = Resources.UnknownTypeName;
            }

            string recordLine =
                DateTime.Now.ToShortDateString() + "-" +
                        DateTime.Now.ToLongTimeString() + " - " +
                        tyepeName + "." + methodName +
                        ": " + Message;

            switch (ErrorHandler.LoggingMode)
            {
                case ErrorLoggingModes.None:
                    break;

                case ErrorLoggingModes.Console:
                    Console.WriteLine(recordLine);

                    if (AddLineBreak)
                        Console.WriteLine();

                    break;

                case ErrorLoggingModes.System:
                    throw new NotSupportedException(
                        Resources.LogTargetNotSupported);

                case ErrorLoggingModes.File:
                    try
                    {
                        if (String.IsNullOrEmpty(ErrorHandler.LogFilePath))
                        {
                            throw new ArgumentException(
                                Resources.LogFilePathNotSet);
                        }

                        using (StreamWriter sr = new StreamWriter(
                            ErrorHandler.LogFilePath, true))
                        {
                            sr.WriteLine(recordLine);

                            if (AddLineBreak)
                                sr.WriteLine();
                        }
                    }
                    catch (ObjectDisposedException ex)
                    {
                        ErrorHandler.LoggingMode = ErrorLoggingModes.Console;
                        ErrorHandler.LogMessage(
                            Resources.WriteToLogFileFailed +
                            ex.Message, true);
                    }
                    catch (IOException ex)
                    {
                        ErrorHandler.LoggingMode = ErrorLoggingModes.Console;
                        ErrorHandler.LogMessage(
                            Resources.WriteToLogFileFailed +
                            ex.Message, true);
                    }
                    catch (SecurityException ex)
                    {
                        ErrorHandler.LoggingMode = ErrorLoggingModes.Console;
                        ErrorHandler.LogMessage(
                            Resources.WriteToLogFileFailed +
                            ex.Message, true);
                    }

                    break;

                default:
                    break;
            }

            return;
        }//end:LogMessage
    }
    /// <summary>
    /// Holds possible error logging targets.
    /// </summary>
    internal enum ErrorLoggingModes
    {
        //Do not produce any output
        None,

        //Log to the console using Console.WriteLine
        Console,

        //Writes an entry to the system event log
        System,

        //Log to a text file
        File
    }
}
